package client;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import commons.Message;
import commons.OMGProtocol;

/**
 * This is the main client class. This class manages the data transfer 
 * between server and client for the client side. Tasks of this class:
   1.	Takes message from OMCProtocolForClient class and sends to server
   2.	Receives messages from server and delegates to OMCProtocolForClient.java class. 

 */

class OMGPClient {

	private static final int PORT = 4171;
	private Socket socket;
	private DataInputStream in;
	private DataOutputStream out;
	String servername="";

	public OMGPClient(){
		try {
			// Connect
			BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
			while(servername.length()<4 || servername.length()>16)
			{
				System.out.println("Server: Please enter server's IP address: ");
				try {
					servername = userInput.readLine();
				} 
				catch (IOException e) 
				{
					System.err.println(" Exception in reading server's IP->"+e.getMessage());
				}
			}

			socket = new Socket(servername, PORT);
			out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
			in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

			// Instantiate protocol
			OMGProtocolForClient oProtocol = new OMGProtocolForClient(servername);

			// Send authentication request by starting DFA
			Message messageToSend = null;
			Message currentServerMessage = new Message();
			int pastState = -1;
			do {		
				if(oProtocol.getState() != pastState) {
					System.err.println("Client is in state: " + oProtocol.getStateDescription());
					pastState = oProtocol.getState();
				}

				// Get the next message if there is one
				if(in.available() > 0 && currentServerMessage.isRead()) {
					try {
						currentServerMessage = new Message(in);
						System.err.println("Message received: " + currentServerMessage.getMessageDescription());
					} catch (Exception e) {
						System.err.println("Malformed message, being fuzzed?");
					}
				}


				// Run the DFA
				try {
					messageToSend = oProtocol.runDFA(currentServerMessage);
				} catch (ClassNotFoundException e) {
					System.err.println("Error with game data ->"+e.getMessage());
				}

				// Check if there's a message to send
				if(messageToSend != null) { 
					try{
						messageToSend.send(out);
					} catch(Exception e) {
						System.err.println("Error sending message!");
					}
				}				

			}while (oProtocol.getState() != OMGProtocol.NONE);


			socket.close();
			in.close();
			out.close();
		} catch (UnknownHostException e) {
			System.err.println("Unable to connect, Server is unknown->"+e.getMessage());
		} catch (SocketException e1) {
			System.err.println(" exception->"+e1.getMessage());
		}catch (IOException e) {
			System.err.println(" IOException in creating connection->"+e.getMessage());
		}
	}


	public static void main(String args[]) {
		new OMGPClient();
	}
}
